home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Burning & Media / GB-PVR 1.2.13 / GBPVR10213.msi / Cabs.w1.cab / Download.aspx.cs463 < prev    next >
Text File  |  2007-07-18  |  16KB  |  458 lines

  1. using System;
  2. using System.Collections;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.IO;
  8. using System.Runtime.Remoting.Contexts;
  9. using System.Text.RegularExpressions;
  10. using System.Threading;
  11. using System.Web;
  12. using System.Web.SessionState;
  13. using System.Web.UI;
  14. using System.Web.UI.WebControls;
  15. using System.Web.UI.HtmlControls;
  16. using System.Xml;
  17. using GBPVRSchedule;
  18. using Microsoft.Win32;
  19. using System.Drawing;
  20.  
  21. using Microsoft.Win32;
  22.  
  23. using GBPVR.Public;
  24.  
  25. using ICSharpCode.SharpZipLib.Zip;
  26.  
  27. namespace gbweb
  28. {
  29.     /// <summary>
  30.     /// Summary description for Download.
  31.     /// </summary>
  32.     public class Download : IRequiresSessionState, IHttpHandler
  33.     {
  34.         private const int buffersize = 500000; // bytes (this is size of packet)
  35.         private const int bufferdelay = 100;   // milliSeconds (this is time between end of packet n, and start of packet n + 1)
  36.         // Where Bps = bytes/sec:
  37.         //  buffersize * bufferdelay gives us our max download rate of 5MBps.
  38.         //   (very roughly because we delay between packets (start2-end1), and don't count time between the start of packets (start2-start1)
  39.         //  Moonlight encoder default is VBR with an average of 0.4MBps, and max of 0.9MBps.
  40.         //  The maximum rate possible that Moonlight supports is 1.5MBps.
  41.  
  42.         public enum InternalFiles
  43.         {
  44.             Log = -1,
  45.             LibraryFile = -2,
  46.             LiveTV = -3,
  47.             LibraryFolder = -4,
  48.             ChannelIcon = -5,
  49.             Photo = -6,
  50.             ModifiedPhoto = -7
  51.         }
  52.  
  53.         #region IHttpHandler Members
  54.  
  55.         public void ProcessRequest(HttpContext context)
  56.         {
  57.             string path = context.Request.PathInfo.TrimStart('/');
  58.             string[] ridInfo = path.Split(',');
  59.  
  60.             int rid = Convert.ToInt32(ridInfo[0]);
  61.             bool direct = ridInfo[1] == "1";
  62.             path = HttpUtility.UrlDecode(context.Request.Url.Query.TrimStart('?'));
  63.  
  64.             ProcessDownload(context.Request, context.Response, direct, rid, path);
  65.         }
  66.  
  67.         public bool IsReusable
  68.         {
  69.             get
  70.             {
  71.                 return true;
  72.             }
  73.         }
  74.  
  75.         #endregion
  76.  
  77.         #region GetDownloadUrl
  78.  
  79.         public static string GetDownloadUrl(bool anon, bool direct, InternalFiles internalType)
  80.         {
  81.             return GetDownloadUrl(anon, direct, (int)internalType);
  82.         }
  83.  
  84.         public static string GetDownloadUrl(bool anon, bool direct, InternalFiles internalType, string path)
  85.         {
  86.             return GetDownloadUrl(anon, direct, (int)internalType, path);
  87.         }
  88.  
  89.         public static string GetDownloadUrl(bool anon, bool direct, int rid)
  90.         {
  91.             return GetDownloadUrl(anon, direct, rid, null);
  92.         }
  93.  
  94.         public static string GetDownloadUrl(bool anon, bool direct, int rid, string path)
  95.         {
  96.             string url;
  97.             if (anon)
  98.             {
  99.                 url = "public/download.aspx?rid=" + PublicDownload.Serialize(rid);
  100.                 if (path != null) url += "&path=" + PublicDownload.Serialize(path);
  101.                 if (direct) url += "&mode=1";
  102.             }
  103.             else
  104.             {
  105.                 url = "public/download.ashx/" + rid.ToString() + (direct ? ",1" : ",0");
  106.                 if (path != null) url += "?" + path;
  107.             }
  108.             return url;
  109.         }
  110.  
  111.         #endregion
  112.         #region ProcessDownload
  113.  
  114.         public static void ProcessDownload(HttpRequest Request, HttpResponse Response, bool direct, int rid, string path)
  115.         {
  116.             Schedule scheduleHelper = Global.Schedule;
  117.  
  118.             string fileName = null;
  119.             string contentType = null;
  120.             bool attachment = true;
  121.             bool seekable = true;
  122.  
  123.             ScheduledRecording recording = null;
  124.  
  125.             switch (rid)
  126.             {
  127.                 case (int)InternalFiles.Log:
  128.                     string logfolder = typeof(GBPVR.Public.ScheduledRecording).Assembly.GetModules()[0].FullyQualifiedName;
  129.                     logfolder = logfolder.Substring(0, logfolder.LastIndexOf(@"\")) + "\\logs";
  130.                     string logname = AppDomain.CurrentDomain.FriendlyName + ".log";
  131.                     fileName = Path.Combine(logfolder, logname);
  132.                     contentType = "text/plain";
  133.                     seekable = false;
  134.                     attachment = false;
  135.                     break;
  136.                 case (int)InternalFiles.LibraryFile:
  137.                     try
  138.                     {
  139.                         fileName = Library.GetRealPath(path);
  140.                     }
  141.                     catch
  142.                     {
  143.                         return;
  144.                     }
  145.                     break;
  146.                 case (int)InternalFiles.LibraryFolder:
  147.                     handleLibraryFolder(Request, Response, direct, path);
  148.                     break;
  149.                 case (int)InternalFiles.LiveTV:
  150.                     string[] tuners = Info.GetRecordingService().getTunerStatus();
  151.                     string currentStatus = tuners[Convert.ToInt32(path)];
  152.                     Match match = Info.liveTVRegex.Match(currentStatus);
  153.                     XmlNode node = Global.Config.SelectSingleNode("/settings/LiveTVDirectory");
  154.                     if ((node != null) && (match.Captures.Count == 1))
  155.                     {
  156.                         fileName = Path.Combine(node.InnerText, match.Groups[1].ToString());
  157.                     }
  158.                     seekable = false;
  159.                     break;
  160.                 case (int)InternalFiles.ChannelIcon:
  161.                     fileName = Path.Combine(Path.Combine(Global.Settings.GetInstallDir(), @"media\ChannelLogos\"), path);
  162.                     break;
  163.                 case (int)InternalFiles.Photo:
  164.                     //This means we want to stream a photo that does not need to be rotated
  165.                     //Deserialize the passed path
  166.                     fileName = (string) PublicDownload.Deseralize(path);
  167.                     break;
  168.                 case (int)InternalFiles.ModifiedPhoto:
  169.                     //This means we want to stream a photo that someone has requested to rotate.
  170.                     //Deserialize the passed path
  171.                     fileName = (string)PublicDownload.Deseralize(path);
  172.                     //The path contains all the parms needed to find, size and rotate the image so each gets split out into
  173.                     //an array for easy access
  174.                     //0 = filename, 1 = desired heigth, 2 = desired width, 3 = rotation option
  175.                     string[] parm = fileName.Split('~');
  176.                     ModifyPhoto(Response, parm[0], Convert.ToInt32(parm[1]), Convert.ToInt32(parm[2]), Convert.ToInt32(parm[3]));
  177.                     //Since the above already streamed the image then we are done here
  178.                     return;
  179.                     break;    
  180.                 default:
  181.                     ScheduledRecording scheduledRecording = scheduleHelper.GetScheduledRecordingByOID(rid);
  182.                     if (scheduledRecording != null)
  183.                     {
  184.                         recording = scheduledRecording;
  185.                         fileName = recording.getFileName();
  186.                     }
  187.                     break;
  188.             }
  189.  
  190.             if (fileName == null) return;
  191.             
  192.             Response.Clear();
  193.  
  194.             if ((!direct) && (attachment))
  195.             {
  196.                 int seconds = -1;
  197.                 if (recording != null) seconds = (int)((TimeSpan)(recording.getEndTime() - recording.getStartTime())).TotalSeconds;
  198.  
  199.                 Response.AppendHeader("Content-Type", "audio/mpegurl");
  200.                 Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileNameWithoutExtension(fileName) + "." + Global.Settings.playlistExtension + "\"");
  201.                 Response.Write("#EXTM3U\r\n");
  202.                 Response.Write("#EXTINF:" + seconds + "," + Path.GetFileNameWithoutExtension(fileName) + "\r\n");
  203.                 string url = Request.Url.ToString().Replace(
  204.                     Request.Url.Scheme + Uri.SchemeDelimiter + Request.Url.Authority,
  205.                     Request.Url.Scheme + Uri.SchemeDelimiter + Request.Headers["Host"]);
  206.                 url = url.Substring(0, url.IndexOf("public/download.ashx"));
  207.                 url += GetDownloadUrl(true, true, rid, path);
  208.                 Response.Write(url + "\r\n");
  209.                 Response.End();
  210.                 return;
  211.             }
  212.  
  213.             try 
  214.             {
  215.                 RegistryKey fileTypeKey = Registry.ClassesRoot.OpenSubKey(Path.GetExtension(fileName));
  216.                 string autocontentType = (string)fileTypeKey.GetValue("Content Type");
  217.                 fileTypeKey.Close();
  218.                 if (autocontentType != null) contentType = autocontentType;
  219.             }
  220.             catch
  221.             {
  222.             }
  223.  
  224.             if (contentType != null) 
  225.             {
  226.                 Response.AppendHeader("Content-Type", contentType);
  227.             }
  228.  
  229.             Response.Buffer = false;
  230.  
  231.             Stream infile = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  232.             long startbyte = 0;
  233.             long stopbyte = infile.Length - 1;
  234.  
  235.             string range = Request.Headers["Range"];
  236.             if (range != null)
  237.             {
  238.                 Response.StatusCode = 206;
  239.                 string[] info = range.Split('=', '-');
  240.                 if ((info.Length > 1) && (info[1].Length > 0))
  241.                     startbyte = Convert.ToInt64(info[1]);
  242.                 if ((info.Length > 2) && (info[2].Length > 0))
  243.                     stopbyte = Convert.ToInt64(info[2]);
  244.                 Response.AppendHeader("Content-Range", "bytes " + startbyte.ToString() + "-" + stopbyte.ToString() + "/" + infile.Length.ToString());
  245.             }
  246.  
  247.             long length = stopbyte - startbyte + 1;
  248.             if (attachment) 
  249.                 Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(fileName) + "\"");
  250.             else
  251.                 Response.AppendHeader("Content-Disposition", "inline; filename=\"" + Path.GetFileName(fileName) + "\"");
  252.             if (seekable) 
  253.             {
  254.                 Response.AppendHeader("Accept-Ranges", "bytes");
  255.                 try
  256.                 {
  257.                     Response.AppendHeader("Content-Length", length.ToString());
  258.                 }
  259.                 catch (OverflowException)
  260.                 {
  261.                     // ugh, .Net v1.1 defined the Content-Length as an Int32.
  262.                     Response.AppendHeader("Content-Length", Int32.MaxValue.ToString());
  263.                 }
  264.             }
  265.             Response.AppendHeader("icy-name", Path.GetFileName(fileName));
  266.             Response.Cache.SetLastModified(File.GetLastWriteTime(fileName));
  267.             Response.Cache.SetExpires(DateTime.Now.AddDays(1));
  268.  
  269.             infile.Position = startbyte;
  270.  
  271.             WriteLargeFileSlowly(Response, infile, Response.OutputStream, rid.ToString());
  272.  
  273.             Response.End();
  274.         }
  275.  
  276.         private static void WriteLargeFileSlowly(HttpResponse Response, Stream infile, Stream outfile, string logID) 
  277.         {
  278.             // Response.WriteFile(fileName, startbyte, length);
  279.             // WriteFile doesn't allow us to control the max download speed.
  280.             // Also in .Net v1.1 / Cassini it doesn't allow > 2GB files to be downloaded.
  281.  
  282.             byte[] buffer = new byte[buffersize];
  283.  
  284.             int readcount = infile.Read(buffer, 0, buffersize);
  285.  
  286.             while (readcount > 0)
  287.             {
  288.                 try
  289.                 {
  290.                     outfile.Write(buffer, 0, readcount);
  291.                 }
  292.                 catch (Exception ex)
  293.                 {
  294.                     Logger.Error("[" + logID + "]: outfile.Write Exception: " + ex.ToString());
  295.                     break;
  296.                 }
  297.                 Thread.Sleep(bufferdelay);
  298.                 readcount = infile.Read(buffer, 0, buffersize);
  299.                 if (!Response.IsClientConnected) 
  300.                 {
  301.                     Logger.Error("[" + logID + "]: Client Not Connected");
  302.                     break;
  303.                 }
  304.             }
  305.             if (readcount != 0) Logger.Error("[" + logID + "]: Read Count Non-Zero");
  306.             infile.Close();
  307.         }
  308.  
  309.         public static string streamLibraryFolder(HttpRequest Request, string vpath)
  310.         {
  311.             string[] pathparts = vpath.Split(new char[] { '/' }, 3);
  312.             Regex fileFilter = Library.GetRegex(pathparts[0]);
  313.  
  314.             string path = Library.GetRealPath(vpath);
  315.  
  316.             string[] filenames = Directory.GetFiles(path);
  317.             Array.Sort(filenames);
  318.  
  319.             string tmpDir = Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
  320.             FileInfo playlist = new FileInfo(tmpDir + "\\playlist.m3u");
  321.             StreamWriter sw = playlist.CreateText();
  322.  
  323.             //sw.WriteLine("Content-Type", "audio/mpegurl");
  324.             //sw.WriteLine("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(Path.GetDirectoryName(path)) + "." + Global.Settings.playlistExtension + "\"");
  325.             sw.Write("#EXTM3U\r\n");
  326.  
  327.             string urlroot = Request.Url.ToString().Replace(
  328.                 Request.Url.Scheme + Uri.SchemeDelimiter + Request.Url.Authority,
  329.                 Request.Url.Scheme + Uri.SchemeDelimiter + Request.Headers["Host"]);
  330.             if (urlroot.Contains("Player.aspx"))
  331.             {
  332.                urlroot = urlroot.Substring(0, urlroot.IndexOf("Player.aspx")); 
  333.             }
  334.             
  335.             foreach (string filename in filenames)
  336.             {
  337.                 if ((filename == Path.GetFullPath(filename)) && (fileFilter.IsMatch(filename)))
  338.                 {
  339.                     sw.Write("#EXTINF:0," + Path.GetFileNameWithoutExtension(filename) + "\r\n");
  340.                     //string url =
  341.                     //    urlroot + GetDownloadUrl(true, true, Download.InternalFiles.LibraryFile, vpath + Path.GetFileName(filename));
  342.                     sw.Write(filename + "\r\n");
  343.                 }
  344.             }
  345.             sw.Close();
  346.             return(playlist.Name);
  347.         }
  348.  
  349.         private static void handleLibraryFolder(HttpRequest Request, HttpResponse Response, bool direct, string vpath)
  350.         {
  351.             string[] pathparts = vpath.Split(new char[] {'/'}, 3);
  352.             Regex fileFilter = Library.GetRegex(pathparts[0]);
  353.  
  354.             string path = Library.GetRealPath(vpath);
  355.  
  356.             string[] filenames = Directory.GetFiles(path);
  357.             Array.Sort(filenames);
  358.  
  359.             if (!direct) 
  360.             {
  361.                 Response.AppendHeader("Content-Type", "audio/mpegurl");
  362.                 Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(Path.GetDirectoryName(path)) + "." + Global.Settings.playlistExtension + "\"");
  363.                 Response.Write("#EXTM3U\r\n");
  364.  
  365.                 string urlroot = Request.Url.ToString().Replace(
  366.                     Request.Url.Scheme + Uri.SchemeDelimiter + Request.Url.Authority,
  367.                     Request.Url.Scheme + Uri.SchemeDelimiter + Request.Headers["Host"]);
  368.                 urlroot = urlroot.Substring(0, urlroot.IndexOf("public/download.ashx"));
  369.                 foreach (string filename in filenames)
  370.                 {
  371.                     if ((filename == Path.GetFullPath(filename)) && (fileFilter.IsMatch(filename)))
  372.                     {
  373.                         Response.Write("#EXTINF:0," + Path.GetFileNameWithoutExtension(filename) + "\r\n");
  374.                         string url = 
  375.                             urlroot + GetDownloadUrl(true, true, Download.InternalFiles.LibraryFile, vpath + Path.GetFileName(filename));
  376.                         Response.Write(url + "\r\n");
  377.                     }
  378.                 }
  379.             } 
  380.             else 
  381.             {
  382.                 Response.AppendHeader("Content-Type", "application/zip");
  383.                 Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(Path.GetDirectoryName(path)) + ".zip\"");
  384.  
  385.                 ZipOutputStream s = new ZipOutputStream(Response.OutputStream);
  386.                 s.SetLevel(0);
  387.  
  388.                 foreach (string filename in filenames)
  389.                 {
  390.                     if ((filename == Path.GetFullPath(filename)) && (fileFilter.IsMatch(filename)))
  391.                     {
  392.                         FileStream fs = File.OpenRead(filename);
  393.  
  394.                         ZipEntry entry = new ZipEntry(Path.Combine(Path.GetFileName(Path.GetDirectoryName(filename)), Path.GetFileName(filename)));
  395.                         entry.Size = fs.Length;
  396.                         s.PutNextEntry(entry);
  397.  
  398.                         WriteLargeFileSlowly(Response, fs, s, filename);
  399.                         fs.Close();
  400.                     }
  401.                 }
  402.  
  403.                 s.Finish();
  404.                 s.Close();
  405.  
  406.             }
  407.  
  408.             Response.End();
  409.         }
  410.  
  411.         private static void ModifyPhoto(HttpResponse Response, string filepath, int H, int W, int R)
  412.         {
  413.  
  414.             //Create the image from the file location
  415.             System.Drawing.Image image = System.Drawing.Image.FromFile(filepath);
  416.  
  417.             //Rotate the image based on what the user selected
  418.             switch (R)
  419.             {
  420.                 case 1:
  421.                     {
  422.                         image.RotateFlip(RotateFlipType.Rotate90FlipNone);
  423.                         break;
  424.                     }
  425.                 case 2:
  426.                     {
  427.                         image.RotateFlip(RotateFlipType.Rotate180FlipNone);
  428.                         break;
  429.                     }
  430.                 case 3:
  431.                     {
  432.                         image.RotateFlip(RotateFlipType.Rotate270FlipNone);
  433.                         break;
  434.                     }
  435.             }
  436.  
  437.             // create a new image that matches the size that the user wants
  438.             System.Drawing.Image thumbnailImage = image.GetThumbnailImage(W, H, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
  439.  
  440.             //Write (save) the new image back to the browser....in this case it is filling the image control
  441.             thumbnailImage.Save(Response.OutputStream, ImageFormat.Jpeg);
  442.             //Celanup
  443.             image.Dispose();
  444.             thumbnailImage.Dispose();
  445.             Response.Flush();
  446.  
  447.         }
  448.  
  449.         public static bool ThumbnailCallback()
  450.         {
  451.             return true;
  452.         }
  453.  
  454.         #endregion
  455.  
  456.     }
  457. }
  458.